#pragma once

#include <iostream>
#include <pthread.h>
#include <memory>
#include <semaphore.h>
#include <vector>
#include <unistd.h>
#include <string.h>
#include "Task.hpp"

using namespace std;

static const int N = 5;

template <class T>
struct RingQueue
{
public:
    RingQueue(int num = N)
        : _ring(num), _capacity(num)
    {
        sem_init(&_data_sem, 0, 0);
        sem_init(&_space_sem, 0, num);
        pthread_mutex_init(&p_mutex,nullptr);
        pthread_mutex_init(&c_mutex,nullptr);
        c_step = p_step = 0;
    }
    void push(const T &in)
    {
        //信号量的作用是控制生产者和消费者的行为，确保它们之间的同步
        //而互斥锁的作用是保护共享的环形缓冲区不会被多个线程同时访问
        sem_wait(&_space_sem); // P()
        pthread_mutex_lock(&p_mutex);
        _ring[p_step++] = in;  // 将数据放入
        p_step %= _capacity;
        sem_post(&_data_sem); // V()
        pthread_mutex_unlock(&p_mutex);
    }
    void pop(T *out)
    {
        sem_wait(&_data_sem);
        pthread_mutex_lock(&c_mutex);
        *out = _ring[c_step++];
        c_step %= _capacity;
        sem_post(&_space_sem);
        pthread_mutex_unlock(&c_mutex);
    }
    ~RingQueue()
    {
        sem_destroy(&_data_sem);
        sem_destroy(&_space_sem);
        pthread_mutex_destroy(&p_mutex);
        pthread_mutex_destroy(&c_mutex);
    }

private:
    int _capacity;
    std::vector<T> _ring; // 环形队列
    sem_t _data_sem;      // 消费者关心
    sem_t _space_sem;     // 生产者关心
    int c_step;           // 消费者位置
    int p_step;           // 生产者位置
    pthread_mutex_t c_mutex;//消费者和消费者也具有竞争关系。因此需要加锁
    pthread_mutex_t p_mutex;//生产者和生产者也具有竞争关系
};